import type { HttpError, HttpRequestConfig, HttpResponse, HttpTask } from '../../luch-request/index.js'

import Cache from '../../cache/index.js'
import uuid from './utils/uuid.js'

interface CacheRule {
  /** @description http响应状态码，默认只缓存200的数据 */
  statusCode?: number
  /** @description 业务状态码值,如业务返回code=200,则busiCode为200,,返回message='成功', 则busiCode为[成功] */
  busiCode?: Record<string, any>
  /** @description 业务状态码key值，如业务数据返回{data:{},msg:'success'},则busiKey为[data],如果为空则不缓存 */
  busiKey?: string
  /** @description 缓存时间，输入数字单位ms，默认为0，永久缓存 ，1d 为一天，1h为一小时，1m为一分钟 */
  cacheTime?: number | `${number}d` | `${number}h` | `${number}m`
  /** @description 缓存模式，默认为lasting，memory为内存缓存，lasting为持久缓存 */
  cacheMode?: 'memory' | 'lasting'
  /** @description 如果缓存的目标对象为空则不缓存 */
  cacheNotEmpty?: boolean
}
type Method = 'GET' | 'POST'
export interface CacheConf {
  GET?: CacheRule
  POST?: CacheRule
}
/**
 * @description 测试输入的数据是否是空，数组和对象无值为空,返回Boolean为空
 */
function isValidVal(obj: any) {
  if (!obj) return
  return (Array.isArray(obj) && obj.length > 0) || (typeof obj === 'object' && Object.keys(obj).length > 0)
}
const cacheRules: CacheConf = {
  POST: {
    statusCode: 200,
    busiCode: { code: ['0000', 200], sucCode: 400 },
    busiKey: 'data',
    cacheMode: 'lasting',
    cacheTime: '1d',
    cacheNotEmpty: true,
  }
}
/**
 * @interface CacheConf
 */

/**
 * @param {boolean} disabled 禁用缓存插件
 * @param {CacheConf} 缓存配置
 */
export function cacheResPlugin(cacheRule: CacheConf = cacheRules) {
  return {
    name: 'cacheResPlugin',
    onRequestSuccess: (config: HttpRequestConfig<HttpTask>) => {
      const getCacheRule = cacheRule[config.method as Method]

      if (getCacheRule && config.custom!.cache === true) {
        const { cacheMode } = getCacheRule
        config.custom!.__USE_CACHE__ = true
        config.custom!.__CACHE_CONFIG__ = getCacheRule

        const _uid = config.custom!.uuid
        const cacheKey = uuid(config, _uid, config.custom!.cacheMode || cacheMode) as string
        config.custom!.__UID__ = cacheKey

        if (config.custom!.refresh === true) {
          Cache.remove(cacheKey) // 如果需要刷新数据则清除
          config.custom!.__USE_CACHE__ = false
        }
        else {
          const hasCache = Cache.get(cacheKey)
          if (hasCache) {
            config.custom!.__SKIP_FETCH__ = true
            config.custom!.__SERVE_DATA__ = hasCache
          }
        }
      }
      return config
    },
    onResponseSuccess: (response: HttpResponse<any, HttpTask>) => {
      // 存在说明是本地缓存，response实际变成了config
      // 构造一个假的response结构

      if ((response as HttpRequestConfig<HttpTask>)?.custom?.__SKIP_FETCH__) {
        return {
          cache: true,
          statusCode: 200,
          config: response,
          data: (response as HttpRequestConfig<HttpTask>)?.custom?.__SERVE_DATA__
        }
      }
      /* 对响应成功做点什么 */
      const { data, config, statusCode: _statusCode } = response
      const { statusCode, busiCode, cacheTime, busiKey, cacheNotEmpty } = config.custom!.__CACHE_CONFIG__ // 缓存配置
      /**
       * 缓存条件,比如返回下列结构 busiCodeKey为code busiCode为1000, busiKey为data
       * {
       *   code: 1000,
       *   errcode: 2000
       *   data: {a:1,b:2}
       * }
       */
      const busiSuc = Object.keys(busiCode).find(key => Array.isArray(busiCode[key]) ? busiCode[key].includes(data[key]) : data[key] === busiCode[key])
      const needCache = config.custom!.__USE_CACHE__ && _statusCode === statusCode && busiSuc

      if (needCache) {
        const cacheKey = config.custom!.__UID__
        const _cacheTime = config.custom!.cacheTime || cacheTime || 0

        if (!cacheNotEmpty) { // 为false则任意数据都缓存
          Cache.set(cacheKey, data, _cacheTime)
        }
        else if (isValidVal(data[busiKey])) {
          // 需要缓存不为空的数据
          Cache.set(cacheKey, data, _cacheTime)
        }
      }
      return response
    }
  }
}
